/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package pgentity;

import config.PGConfig;
import db.DBContext;
import db.PGKeys;
import db.RedisKey;
import java.util.HashMap;
import java.util.Map;
import share.PGHelper;
import share.PGMacro;

/**
 *
 * @author Salm
 */
public class FindEggs implements PGEntity {
    private final String uid;
    private final RedisKey redisKey;
    private final Map<String, String> newValues = new HashMap();
    
    private long endEmployTime;
    
    private State state;
    
    private String findEgg;
    private long foundTime;
    private EggOption[] options;
    
    private long nextFind;

    private FindEggs(String uid) {
        this.uid = uid;
        this.redisKey = key(uid);
    }
    
    public static FindEggs getFindEggs(String uid)
    {
        FindEggs findEggs = new FindEggs(uid);
        findEggs.updateFromDB();
        
        return findEggs;
    }
    
    public static RedisKey key(String uid)
    {
        return PGKeys.USERS.getChild(uid).getChild(PGKeys.FD_FINDEGGS);
    }
    
    public static int getNOptions()
    {
        return PGConfig.inst().findEggs().options().size();
    }
    
    public static void destroy(String uid)
    {
        DBContext.Redis().del(key(uid));
    }
    
    @Override
    public void updateFromDB() {
        Map<String, String> data = DBContext.Redis().hgetall(redisKey);
        fillFromDB(data);
    }
    
    private void fillFromDB(Map<String, String> data)
    {
        this.endEmployTime = PGHelper.toLong(data.get(PGMacro.FENPC_END_EMPLOY));
        this.state = State.parse(data.get(PGMacro.FENPC_STATE));
        this.findEgg = data.get(PGMacro.FENPC_EGG);
        this.foundTime = PGHelper.toLong(data.get(PGMacro.FENPC_FOUND_TIME));
        this.nextFind = PGHelper.toLong(data.get(PGMacro.FENPC_NEXT_FIND));
        
        this.options = new EggOption[getNOptions()];
        for (int i = 0; i < options.length; i++) {
            EggOption option = new EggOption(i, newValues);
            option.updateFromData(data);
            options[i] = option;
        }
    }

    @Override
    public void saveToDB() {
        if (!newValues.isEmpty())
        {
            DBContext.Redis().hset(redisKey, newValues);
            newValues.clear();
        }
    }

    public long getEndEmployTime() {
        return endEmployTime;
    }

    public void setEndEmployTime(long endEmployTime) {
        this.endEmployTime = endEmployTime;
        newValues.put(PGMacro.FENPC_END_EMPLOY, String.valueOf(endEmployTime));
    }

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
        newValues.put(PGMacro.FENPC_STATE, this.state.name());
    }

    public String getFindEgg() {
        return findEgg;
    }

    public void setFindEgg(String findEgg) {
        this.findEgg = findEgg;
        newValues.put(PGMacro.FENPC_EGG, this.findEgg);
    }

    public long getFoundTime() {
        return foundTime;
    }

    public void setFoundTime(long foundTime) {
        this.foundTime = foundTime;
        newValues.put(PGMacro.FENPC_FOUND_TIME, String.valueOf(this.foundTime));
    }

    public long getNextFind() {
        return nextFind;
    }

    public void setNextFind(long nextFind) {
        this.nextFind = nextFind;
        newValues.put(PGMacro.FENPC_NEXT_FIND, String.valueOf(this.nextFind));
    }

    public EggOption[] getOptions() {
        return options;
    }
    
    public Object buildAMF()
    {
        Map<String, Object> data = new HashMap();
        data.put(PGMacro.FENPC_STATE, state.name());
        data.put(PGMacro.FENPC_END_EMPLOY, endEmployTime);
        
        switch (state)
        {
            case LEVEL_LOCKED:
                break;
            case LOCKED:
                break;
            case COOLDOWN:
                data.put(PGMacro.FENPC_NEXT_FIND, nextFind);
                break;
            case CHOOSE_EGGS:
                break;
            case FINDING:
                data.put(PGMacro.FENPC_EGG, findEgg);
                data.put(PGMacro.FENPC_FOUND_TIME, foundTime);
                break;
            case FOUND:
                data.put(PGMacro.FENPC_EGG, findEgg);
                data.put(PGMacro.FENPC_OPTIONS, buildOptionsAMF());
                break;
        }
        
        return data;
    }
    
    private Object buildOptionsAMF()
    {
        Map<String, Object> data = new HashMap();
        for (int i = 0; i < options.length; i++) {
            data.put(String.valueOf(i), options[i].buildAMF());
        }
        
        return data;
    }
    
    public Object dump()
    {
        return DBContext.Redis().hgetall(key(uid));
    }
    
    public static enum State
    {
        LEVEL_LOCKED,
        LOCKED,
        COOLDOWN,
        CHOOSE_EGGS,
        FINDING,
        FOUND;
        
        public static State parse(String st)
        {
            try
            {
                return valueOf(st);
            }
            catch (Exception ex)
            {
                return LEVEL_LOCKED;
            }
        }
    }
    
    public static class EggOption
    {
        private final int opIndex;
        private final Map<String, String> newVals;
        private int nEgg;
        private int coinPrice;
        private int goldPrice;

        public EggOption(int opIndex, Map<String, String> newVals) {
            this.opIndex = opIndex;
            this.newVals = newVals;
        }
        
        public void updateFromData(Map<String, String> data)
        {
            this.nEgg = PGHelper.toInt(data.get(PGMacro.FENPC_NEGG + opIndex));
            this.coinPrice = PGHelper.toInt(data.get(PGMacro.FENPC_COIN_PRICE + opIndex));
            this.goldPrice = PGHelper.toInt(data.get(PGMacro.FENPC_GOLD_PRICE + opIndex));
        }

        public int getnEgg() {
            return nEgg;
        }

        public int getCoinPrice() {
            return coinPrice;
        }

        public int getGoldPrice() {
            return goldPrice;
        }

        public void setNOfEgg(int nEgg) {
            this.nEgg = nEgg;
            newVals.put(PGMacro.FENPC_NEGG + opIndex, String.valueOf(this.nEgg));
        }

        public void setCoinPrice(int coinPrice) {
            this.coinPrice = coinPrice;
            newVals.put(PGMacro.FENPC_COIN_PRICE + opIndex, String.valueOf(this.coinPrice));
        }

        public void setGoldPrice(int goldPrice) {
            this.goldPrice = goldPrice;
            newVals.put(PGMacro.FENPC_GOLD_PRICE + opIndex, String.valueOf(this.goldPrice));
        }
        
        public Object buildAMF()
        {
            Map<String, Object> data = new HashMap(3);
            data.put(PGMacro.FENPC_NEGG, nEgg);
            data.put(PGMacro.FENPC_GOLD_PRICE, goldPrice);
            data.put(PGMacro.FENPC_COIN_PRICE, coinPrice);
            
            return data;
        }
    }
}